<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <script>
    const bucket = new WeakMap();
    let activeEffect;
    const effectStack = []; //新增
    //原始数据
    const data = {
      text: "hello word",
      text2: "hello2",
      foo: 1
    }
    //设置里面的函数抽象到’追踪‘
    function track(target, key) {
      if (!activeEffect) {
        return;
      }
      let depsMap = bucket.get(target);
      if (!depsMap) {
        //用对象来做key
        bucket.set(target, (depsMap = new Map()))
      }
      let deps = depsMap.get(key);
      if (!deps) {
        depsMap.set(key, (deps = new Set()));
      }
      deps.add(activeEffect);
    }
    //设置的代码，抽象到这里
    function trigger(target, key) {

      const depsMap = bucket.get(target);
      if (!depsMap) {
        return;
      }
      const effects = depsMap.get(key);
      // effects && effects.forEach(fn => fn());
      //新增
      const effectToRun = new Set();
      effects && effects.forEach(fn => {
        if (fn !== activeEffect) {
          effectToRun.add(fn);
        }
      });
      effectToRun.forEach(fn => {
        //副作用函数，是否存在调度器？？？？？
        console.log("被手机的effect函数是fn：", fn)
        if (fn.options && fn.options.scheduler) {
          fn.options.scheduler(fn)
        } else {
          fn();
        }
      })

    }
    const obj = new Proxy(data, {
      get(target, key) {
        track(target, key);
        return target[key]; //返回对应的值
      },
      set(target, key, newVal) {
        target[key] = newVal;
        trigger(target, key);
      }
    })

    //用于注册副作用函数
    function effect(fn, options = {}) {
      const effectFn = () => {
        activeEffect = fn;
        //添加到数组最后
        effectStack.push(effectFn); //函数把自己放到数组里面
        fn();
        //
        effectStack.pop(); //移除掉数组最后一个
        activeEffect = effectStack[effectStack.length - 1];
      }
      fn.options = options; //fn才是effect函数
      if (!options.lazy) {
        effectFn();
      }

      return effectFn;
    }
    let tmp1, tmp2;
    const effectFn = effect(() => {
      console.log("obj.foo", obj.foo)
    }, {
      lazy: true
    });
    obj.foo += 1;
    effectFn();
  </script>
</body>

</html>